"""最简单的最小二乘法实现"""

import matplotlib.pyplot as plt
import numpy as np


class SimpleLatestSquares(object):
    """
    一个巨简单的最小二乘法实现
    """

    def __init__(self, w, b):
        self.real_w = w
        self.real_b = b
        self.guess_w = 0
        self.guess_b = 0
        self.x = []
        self.y = []

    def random_raw_data(self, base=20, min_value=-100, max_value=100, noise_coefficient=800):
        """
        默认生成1000个数据点，随机生成，x的取值范围值在-100 ~ 100间
        """
        noise = (np.random.rand(1, base) - 0.5) * noise_coefficient

        self.x = np.linspace(min_value, max_value, base)
        self.y = self.x * self.real_w + self.real_b + noise

    def compute(self):
        """
        计算w和b的值
        """
        x = self.x
        y = self.y
        average_x = x.mean()
        m = x.shape[0]

        self.guess_w = np.sum(y * (x - average_x)) / (np.sum(np.power(x, 2)) - np.sum(x) ** 2 / m)
        self.guess_b = np.sum(y - x * self.guess_w) / m

    def __str__(self):
        return """原w = {0:f} 原b = {1:f}
预测的w = {2:f} 预测的b = {3:f}
    """.format(self.real_w, self.real_b, self.guess_w, self.guess_b)


if __name__ == '__main__':
    sls = SimpleLatestSquares(-34, -2)
    sls.random_raw_data()
    print(sls)
    sls.compute()
    print(sls)

    plt.plot(sls.x, sls.y.T, 'ro', label='Sample')
    guess_y = sls.x * sls.guess_w + sls.guess_b
    plt.plot(sls.x, guess_y.T, label='forcast')
    plt.title("Simple Latest Sequares")
    plt.legend()
    plt.show()
